from django.shortcuts import render, redirect
from django.views.generic import View
from utils.views import LoginRequired,LoginRequiredJSONMixin,TransactionAtomicMixin
from django.http import HttpResponse
from django.core.urlresolvers import reverse
from django_redis import get_redis_connection
from goods.models import *
from users.models import *
from django.http import JsonResponse
from orders.models import *
from django.utils import timezone
# Create your views here.
from django.db import transaction
from django.core.paginator import Paginator,EmptyPage


class UserOrdersView(View):

    def get(self,request,page):
        user = request.user
        # 查询所有订单
        orders = user.orderinfo_set.all().order_by("-create_time")

        # 遍历所有订单
        for order in orders:
            # 给订单动态绑定：订单状态
            order.status_name = OrderInfo.ORDER_STATUS[order.status]
            # 给订单动态绑定：支付方式
            order.pay_method_name = OrderInfo.PAY_METHODS[order.pay_method]
            order.skus = []
            # 查询订单中所有商品
            order_skus = order.ordergoods_set.all()
            # 遍历订单中所有商品
            for order_sku in order_skus:
                sku = order_sku.sku
                sku.count = order_sku.count
                sku.amount = sku.price * sku.count
                order.skus.append(sku)

        # 分页
        page = int(page)
        try:
            paginator = Paginator(orders, 2)
            page_orders = paginator.page(page)
        except EmptyPage:
            # 如果传入的页数不存在，就默认给第1页
            page_orders = paginator.page(1)
            page = 1

        # 页数
        page_list = paginator.page_range

        context = {
            "orders": page_orders,
            "page": page,
            "page_list": page_list,
        }

        return render(request, "user_center_order.html", context)



class CommitOrderView(LoginRequiredJSONMixin,TransactionAtomicMixin, View):

    def post(self,request):
        # 获取参数：user,address_id,pay_method,sku_ids,count
        user = request.user
        address_id = request.POST.get('address_id')
        pay_method = request.POST.get('pay_method')
        sku_ids = request.POST.get('sku_ids')

        # 校验参数：all([address_id, pay_method, sku_ids])
        if not all([address_id,pay_method,sku_ids]):
            return JsonResponse({'code':2,'message':'参数不完整!'})
        # 判断地址
        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code':3,'message':'地址错误!'})
        # 判断支付方式
        # if pay_method not in OrderInfo.PAY_METHOD:
        #     return JsonResponse({'code': 4, 'message': '支付方式错误'})

        if pay_method not in OrderInfo.PAY_METHOD:
            return JsonResponse({'code': 4, 'message': '支付方式错误'})

        # 截取出sku_ids列表
        sku_ids = sku_ids.split(',')

        redis_coon = get_redis_connection('default')

        order_id = timezone.now().strftime('%Y%m%d%H%M%S') + str(user.id)

        # 定义临时变量
        total_count = 0
        total_amount = 0

        # 在操作数据库前创建事务保存点
        save_point = transaction.savepoint()

        try:
            # 创建 OrderInfo对象
            order = OrderInfo.objects.create(
                order_id=order_id,
                user = user,
                address = address,
                total_amount = 0,
                trans_cost = 10,
                pay_method = pay_method,
            )


            # 遍历sku_ids
            for sku_id in sku_ids:
                for i in range(3):
                    # 循环取出sku，判断商品是否存在
                    try:
                        sku = GoodsSKU.objects.get(id=sku_id)
                    except GoodsSKU.DoesNotExist:
                        # 回滚
                        transaction.savepoint_rollback(save_point)
                        return JsonResponse({'code': 5, 'message': '商品不存在'})

                    # 获取商品数量，判断库存 (redis)
                    sku_count = redis_coon.hget('cart_%s'%user.id,sku_id)
                    sku_count = int(sku_count)

                    if sku_count > sku.stock:
                        # 回滚
                        transaction.savepoint_rollback(save_point)
                        return JsonResponse({'code': 6, 'message': '库存不足'})

                    # # 减少sku库存
                    # sku.stock -= sku_count
                    #
                    # # 增加sku销量
                    # sku.sales += sku_count
                    # sku.save()
                    # 乐观锁
                    origin_stock = sku.stock
                    new_stock = origin_stock - sku.stock
                    ret = GoodsSKU.objects.filter(id=sku_id,stock=origin_stock).update(stock=new_stock,sales=new_stock)
                    if not ret and i < 2:
                        transaction.savepoint_rollback(save_point)
                        continue
                    elif ret == 0 and i==2:
                        transaction.savepoint_rollback(save_point)
                        return JsonResponse({'code': 8, 'message': ' -- 库存不足'})

                    amount = sku.price * sku_count

                    # 保存订单商品数据OrderGoods(能执行到这里说明无异常)
                    # 先创建商品订单信息
                    OrderGoods.objects.create(
                        order=order,
                        sku = sku,
                        count = sku_count,
                        price = sku.price,
                    )

                    # 计算总数和总金额
                    total_count += sku_count
                    total_amount += amount

                    break

            # 修改订单信息里面的总数和总金额(OrderInfo)
            order.total_count = total_count
            order.total_amount =total_amount + 10
            order.save()
        except Exception:
            # 暴力回滚
            transaction.savepoint_rollback(save_point)
            return JsonResponse({'code':7,'message':'下单失败,暴力回滚!'})

        # 没有异常，就手动提交
        transaction.savepoint_commit(save_point)

        # 订单生成后删除购物车(hdel)
        redis_coon.hdel('cart_%s'%user.id,*sku_ids)

        # 响应结果
        return JsonResponse({'code': 0, 'message': '提交成功!'})


class PlaceOrderView(LoginRequired, View):
    """订单确认 页面 !"""

    def post(self, request):

        # 判断用户是否登陆：LoginRequiredMixin
        # 获取参数：sku_ids, count
        sku_ids = request.POST.get('sku_ids')
        count = request.POST.get('count')
        # 校验sku_ids参数：not
        if sku_ids is None:
            return redirect(reverse('cart:info'))

        skus = []
        total_count = 0
        total_sku_amount = 0
        trans_cost = 10
        total_amount = 0
        redis_coon = get_redis_connection('default')

        # 校验count参数：用于区分用户从哪儿进入订单确认页面
        # 从详情页面过来的为真
        user = request.user
        if count:
            # 查询商品数据
            try:
                sku = GoodsSKU.objects.get(id=sku_ids)
            except:
                return redirect(reverse('cart:info'))
            # 商品的数量从request中获取,并try校验
            try:
                sku_count = int(count)
            except Exception:
                return redirect(reverse('goods:detail', args=(sku.id,)))

            if int(count) > sku.stock:
                return redirect(reverse('goods:detail', args=(sku.id,)))
            # 单个商品的 小记 和数量 并添加属性给 sku
            amout = sku.price * sku_count
            sku.sku_count = sku_count
            sku.amount = amout

            skus.append(sku)
            total_count += sku_count
            total_sku_amount += amout

            redis_coon.hset('cart_%s'%user.id,sku.id)

        # 购物车页面过来
        else:
            user = request.user
            # 查询商品数据
            # 商品的数量从redis中获取

            redis_dict = redis_coon.hgetall('cart_%s' % user.id)
            for sku_id, count in redis_dict.items():
                try:
                    sku = GoodsSKU.objects.get(id=sku_id)
                except GoodsSKU.DoesNotExist:
                    return redirect(reverse('cart:info'))
                sku_count = int(count)
                sku_count = int(sku_count)

                amout = sku.price * sku_count
                sku.sku_count = sku_count
                sku.amount = amout
                skus.append(sku)

                total_count += sku_count
                total_sku_amount += amout
        try:
            address = Address.objects.filter(user=request.user).latest('create_time')
        except Address.DoesNotExist:
            address = None  # 模板会做判断，然后跳转到地址编辑页面


        total_amount = total_sku_amount + trans_cost

        # 判断库存：立即购买没有判断库存

        # 查询用户地址信息

        # 构造上下文
        context = {
            'skus': skus,
            'total_count': total_count,
            'total_sku_amount': total_sku_amount,
            'trans_cost': trans_cost,
            'total_amount': total_amount,
            'address': address,
            'sku_ids':','.join(sku_ids)
        }

        # 响应结果:html页面

        return render(request, 'place_order.html', context)
